﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LogicGate.cs" company="pwasiewicz">
//   pwasiewicz
// </copyright>
// <summary>
//   The logic gate.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace LogicSystem.LogicGates
{
    using System.Collections.Generic;
    using System.Linq;

    using LogicSystem.Interfaces;
    using LogicSystem.Wires;

    /// <summary>The logic gate.</summary>
    public abstract class LogicGate
    {
        /// <summary>Initializes a new instance of the <see cref="LogicGate"/> class.</summary>
        internal LogicGate()
        {
            this.InputWires = new List<Wire>();
        }

        /// <summary>
        /// Gets the latency.
        /// </summary>
        public abstract int Latency { get; }

        /// <summary>
        /// Gets or sets output wire.
        /// </summary>
        public Wire OutputWire { get; set; }

        /// <summary>
        /// Gets or sets simulating environment
        /// </summary>
        internal ISimulatingEnvironment<int, LogicGate> SimulatingEnvironment { get; set; }

        /// <summary>
        /// Gets or sets input wires.
        /// Initializes inputWires instance if needed.
        /// </summary>
        internal List<Wire> InputWires { get; set; }

        /// <summary>
        /// Computes output wire state.
        /// </summary>
        /// <returns>The gate's state.</returns>
        public abstract bool ComputeOutput();

        /// <summary>
        /// Refreshes output wire state.
        /// </summary>
        public void Refresh()
        {
            this.OutputWire.State = this.ComputeOutput();
        }

        /// <summary>
        /// Adds input wires to the gate.
        /// </summary>
        /// <param name="wires">The wires collection.</param>
        public void AddInputWires(params Wire[] wires)
        {
            this.InputWires.AddRange(wires);
        }

        /// <summary>
        /// Adds input wires to the gate.
        /// </summary>
        /// <param name="wires">The wires collection.</param>
        public void AddInputWires(IEnumerable<Wire> wires)
        {
            this.AddInputWires(wires.ToArray());
        }
    }
}
